﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Miv
{
    public partial class FormMain : Form
    {

        public FormMain(string [] start_with = null)
        {
            InitializeComponent();
            child_form_list = new List<Tuple<Form, int>>();

            FormMiv miv = New();
            miv.ShowImages(start_with);
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
        }

        List<Tuple<Form, int>> child_form_list;

        public FormMiv New()
        {
            FormMiv miv = new FormMiv();
            Add(miv);
            miv.Show(this);
            return miv;
        }
        public void Add(Form form)
        {
            child_form_list.Add(new Tuple<Form, int>(form, 1));

            FormMiv miv = form as FormMiv;
            if (miv != null)
            {
                miv.Panned += new EventHandler(FormMiv_Panned);
                miv.FormClosed += new FormClosedEventHandler(FormMiv_Closed);
                miv.NewFormCreated += new EventHandler(FormMiv_Created);
                miv.KeyDown += new KeyEventHandler(FormMiv_KeyDown);

                ToolStripMenuItem menu_item;
                ToolStripSeparator menu_separator;

                menu_separator = new ToolStripSeparator();
                miv.RightClickMenu.Items.Insert(0, menu_separator);

                menu_item = new ToolStripMenuItem("Tile Identically", null, new EventHandler(TileIdentically));
                miv.RightClickMenu.Items.Insert(0, menu_item);

                menu_item = new ToolStripMenuItem("Tile Vertically", null, new EventHandler(TileVertically));
                miv.RightClickMenu.Items.Insert(0, menu_item);

                menu_item = new ToolStripMenuItem("Tile Horizontally", null, new EventHandler(TileHorizontally));
                miv.RightClickMenu.Items.Insert(0, menu_item);

                menu_separator = new ToolStripSeparator();
                miv.RightClickMenu.Items.Insert(0, menu_separator);

                menu_item  = new ToolStripMenuItem("Match All", null, new EventHandler(MatchViews));
                miv.RightClickMenu.Items.Insert(0, menu_item);

                menu_separator = new ToolStripSeparator();
                miv.RightClickMenu.Items.Add(menu_separator);

                menu_item = new ToolStripMenuItem("Group");
                ToolStripMenuItem group1 = (ToolStripMenuItem)menu_item.DropDownItems.Add("Group 1", null, new EventHandler(SetGroup1));
                group1.Checked = true;
                menu_item.DropDownItems.Add("Group 2", null, new EventHandler(SetGroup2));
                menu_item.DropDownItems.Add("Group 3", null, new EventHandler(SetGroup3));
                menu_item.DropDownItems.Add("Group 4", null, new EventHandler(SetGroup4));
                miv.RightClickMenu.Items.Add(menu_item);


                menu_separator = new ToolStripSeparator();
                miv.RightClickMenu.Items.Add(menu_separator);

                menu_item = new ToolStripMenuItem("Close All", null, new EventHandler(CloseAll));
                miv.RightClickMenu.Items.Add(menu_item);
            }
        }

        public void Delete(Form form)
        {
            int n = IndexOf(form);
            
            if (n >= 0)
            {
                child_form_list.RemoveAt(n);
            }

            if (child_form_list.Count <= 0)
            {
                this.Close();
            }

        }
        public int IndexOf(Object form)
        {
            int n = -1;
            for (int i = 0; i < child_form_list.Count; i++)
            {
                if (child_form_list[i].Item1 == form)
                {
                    n = i;
                    break;
                }
            }
            return n;
        }

        private void FormMiv_Panned(object sender, EventArgs e)
        {
            if (ModifierKeys == Keys.Control)
                return;

            int n = IndexOf(sender);
            int group_id = child_form_list[n].Item2;

            int dx = ((PannedEventArgs)e).X;
            int dy = ((PannedEventArgs)e).Y;

            for (int i = 0; i < child_form_list.Count; i++ )
            {
                if (i == n)
                    continue;

                FormMiv miv = child_form_list[i].Item1 as FormMiv;
                if (miv != null &&
                    child_form_list[i].Item2 == child_form_list[n].Item2 &&
                    miv.WindowState != FormWindowState.Minimized)
                {
                    miv.Shift(dx, dy);
                }
            }
        }
        private void FormMiv_Created(object sender, EventArgs e)
        {
            Form miv = sender as FormMiv;
            if (miv != null)
                Add(miv);
        }
        private void FormMiv_Closed(object sender, FormClosedEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
                Delete((Form)sender);

            if (child_form_list.Count < 1)
                Application.Exit();
        }

        private void FormMiv_KeyDown(object sender, KeyEventArgs e)
        {
            int num1 = 97, num9 = num1 + 8;
            int key1 = 49, key9 = key1 + 8;
            int sel = -1;
            if ((e.KeyValue >= key1) && (e.KeyValue <= key9))
            {
                sel = e.KeyValue - key1;
            }
            else if ((e.KeyValue >= num1) && (e.KeyValue <= num9))
            {
                sel = e.KeyValue - num1;
            }
            if ((sel >= 0) && (sel <= child_form_list.Count - 1))
            {
                child_form_list[sel].Item1.Activate();
            }
                
        }

        private void TileViews(TileMode mode)
        {
            if (mode == TileMode.Identically)
            {
                Form reference_form = ActiveForm;

                if (reference_form != null)
                {
                    foreach (Tuple<Form, int> t in child_form_list)
                    {
                        if (t.Item1 != reference_form)
                        {
                            t.Item1.Location = reference_form.Location;
                            t.Item1.Size = reference_form.Size;
                        }

                    }
                }
            }
            else
            {
                for (int i = 0; i < Screen.AllScreens.Length; i++)
                {
                    int sw = Screen.AllScreens[i].WorkingArea.Width;
                    int sh = Screen.AllScreens[i].WorkingArea.Height;

                    int cnt = 0;
                    for (int j = 0; j < child_form_list.Count; j++)
                    {
                        if (child_form_list[j].Item1.WindowState != FormWindowState.Minimized &&
                            Screen.AllScreens[i].Bounds.Contains(child_form_list[j].Item1.Location))
                            cnt++;
                    }

                    if (cnt > 0)
                    {
                        int col, row;

                        if (mode == TileMode.Horizontally)
                        {
                            row = 1;
                            col = cnt;
                        }
                        else
                        {
                            col = cnt > 6 ? 3 : (cnt > 3 ? 2 : cnt);
                            row = (int)Math.Ceiling(1.0 * cnt / col);
                        }

                        int ww = Screen.AllScreens[i].WorkingArea.Width / col;
                        int wh = Screen.AllScreens[i].WorkingArea.Height / row;

                        int k = 0;
                        for (int j = 0; j < child_form_list.Count; j++)
                        {
                            if (child_form_list[j].Item1.WindowState != FormWindowState.Minimized &&
                                Screen.AllScreens[i].Bounds.Contains(child_form_list[j].Item1.Location))
                            {
                                child_form_list[j].Item1.Location = new Point((k % col) * ww, (k / col) * wh);
                                child_form_list[j].Item1.Size = new Size(ww, wh);

                                k++;
                            }
                        }
                    }

                }
            }
        }
        private void SetGroup(object sender, int group_id)
        {
            ToolStripMenuItem menu_item = (ToolStripMenuItem)sender;
            ToolStrip strip = menu_item.GetCurrentParent();
            foreach(ToolStripMenuItem m in strip.Items)
            {
                if (m == sender)
                    m.Checked = true;
                else
                    m.Checked = false;
            }

            FormMiv miv = ActiveForm as FormMiv;

            if (miv != null)
            {
                int n = IndexOf(miv);
                child_form_list[n] = new Tuple<Form, int>(child_form_list[n].Item1, group_id);
            }
        }
        private void MatchViews(object sender, EventArgs e)
        {
            FormMiv reference_form = ActiveForm as FormMiv;

            if (reference_form != null)
            {
                int n = IndexOf(reference_form);
                for (int i = 0; i < child_form_list.Count; i++)
                {
                    if (i == n)
                        continue;

                    FormMiv miv = child_form_list[i].Item1 as FormMiv;
                    if (miv != null)
                    {
                        if ((child_form_list[i].Item2 == child_form_list[n].Item2) &&
                            (miv.WindowState != FormWindowState.Minimized))
                        {
                            miv.ZoomRate = reference_form.ZoomRate;
                            miv.Offset = reference_form.Offset;
                        }
                    }
                }
            }
        }
        private void CloseAll(object sender, EventArgs e)
        {
            Form[] child_forms = new Form[child_form_list.Count];
            for (int i = 0; i < child_form_list.Count; i++)
            {
                child_forms[i] = child_form_list[i].Item1;
            }

            foreach (Form form in child_forms)
            {
                FormMiv miv = form as FormMiv;
                if (miv != null)
                {
                    if (miv != ActiveForm)
                    {
                        miv.Close();
                    }
                    else
                    {
                        miv.Clear();
                    }
                }
            }
        }
        private void SetGroup1(object sender, EventArgs e)
        {
            SetGroup(sender, 1);
        }
        private void SetGroup2(object sender, EventArgs e)
        {
            SetGroup(sender, 2);
        }
        private void SetGroup3(object sender, EventArgs e)
        {
            SetGroup(sender, 3);
        }
        private void SetGroup4(object sender, EventArgs e)
        {
            SetGroup(sender, 4);
        }
        private void TileHorizontally(object sender, EventArgs e)
        {
            TileViews(TileMode.Horizontally);
        }
        private void TileVertically(object sender, EventArgs e)
        {
            TileViews(TileMode.Vertically);
        }
        private void TileIdentically(object sender, EventArgs e)
        {
            TileViews(TileMode.Identically);
        }

    }

    public enum TileMode
    {
        Horizontally,
        Vertically,
        Identically
    }
}
